#ifndef __TERRAIN_SERIALIZER_H__
#define __TERRAIN_SERIALIZER_H__

#include <cstdint>
#include <cstring>
#include <vector>
#include <map>
#include "TerrainChunk.h"
#include "concurrentqueue.h"
#include <mutex>
#include "ITerrainSerializer.hpp"
#include "Region.hpp"

namespace PocketSurvival
{
    class TerrainSerializer : public ITerrainSerializer
    {
    private:
        std::vector<Region *> m_regionCatchVector;
        moodycamel::ConcurrentQueue<Region *> m_regionQueue;
        std::map<int64_t, Region *> m_regionMap;
        std::mutex m_regionMapMutex;

    private:
        void createRegionCatch(uint8_t count);
        Region *getRegion(int32_t x, int32_t y);
        Region *getNoDataRegion();

    public:
        TerrainSerializer();
        ~TerrainSerializer();

        /**
         * @brief 向 地图区域(Region) 中读取 区块(TerrainChunk) 的数据，
         * 
         * @note 读取前应该先赋值 区块(TerrainChunk) 中的coords数据
         *
         * @param terrainChunk 区块对象
         * @return true 加载成功 | false 加载失败
         */
        virtual bool loadChunk(TerrainChunk *terrainChunk) override;

        /**
         * @brief 将 区块(TerrainChunk) 保存进对应 地图区域(Region) 内
         * @param terrainChunk 区块对象
         * @return true 保存成功 | false 保存失败
         */
        virtual bool saveChunk(TerrainChunk *terrainChunk) override;

        /**
         * @brief 保存服务器上缓存着的所有 区域(Region) 数据到map文件里
         * 
         * @note 保存后不会释放缓存的 区域(Region) 数据
         *       数据保存使用了 GameManager 的线程池进行加速保存
         */
        virtual void saveAllRegion() override;

        /**
         * @brief 保存服务器上缓存着的所有 区域(Region) 数据,
         * @note 该函数不会保存 区域(Region) 数据，调用该函数前，请确保 区域(Region) 数据已经保存
         *       此函数一般用于地形修改了，但不需要的情况下使用，例如：起床战争游戏一局后需要地形重置
         */
        virtual void releaseAllRegion() override;

        /**
         * @brief 保存并释放 区域(Region) 数据
         * 
         * @note 数据保存使用了 GameManager 的线程池进行加速保存
         */
        virtual void saveAndReleaseAllRegion() override;
    };

}

#endif